
// 包含 dev_t
#include <linux/types.h>

// 包含这三个 宏MAJOR MINOR MKDEV
#include <linux/kdev_t.h>

#include <linux/fs.h>
#include <linux/module.h>

#define HELLO_MAJAR 0
#define HELLO_NR_DEVS 2

// 定义主设备号
static int hello_major = HELLO_MAJAR;
// 定义次设备号
static int hello_minor = 0;

// 结合主设备号和次设备号
// 高12位是主设备号，低20位是次设备号
static dev_t hello_dev;

// 次设备号的个数
static int hello_nr_devs = HELLO_NR_DEVS;

module_param(hello_major, int, S_IRUGO);

module_param(hello_minor, int, S_IRUGO);

module_param(hello_nr_devs, int, S_IRUGO);

static int __init chr_init(void);

static void __exit chr_exit(void);

static int __init chr_init(void)
{
    int ret;

    printk(KERN_INFO "begin register chr device module\n");

    if (hello_major)
    {
        hello_dev = MKDEV(hello_major, hello_minor);
        // 使用指定的设备号分配
        ret = register_chrdev_region(hello_dev, hello_nr_devs, "hello_chr");
    }
    else
    {
        // 动态分配主设备号
        ret = alloc_chrdev_region(&hello_dev, hello_minor, hello_nr_devs, "hello_chr");
        hello_major = MAJOR(hello_dev);
    }

    if (ret < 0)
    {
        printk(KERN_WARNING "hello: can't get marjor %d\n", hello_major);
        return ret;
    }

    printk(KERN_INFO "successfully allocate major device: %d, dev_t : %x",hello_major,hello_dev);

    return 0;
}

static void __exit chr_exit(void)
{

    unregister_chrdev_region(hello_dev, hello_nr_devs);
    printk(KERN_INFO "unregister chr device successfully!\n");
}

module_init(chr_init);

module_exit(chr_exit);

//  许可证描述
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("luojunhua");
MODULE_VERSION("V1.0");